/*
 Copyright (c) 2013 MeherTJ G. All rights reserved.
 License: LGPL for personnal study or free software.
 */

#pragma once

#include "zen_color.h"

#include <memory>
#include <vector>

namespace Zen {

	class Image
	{
	public:
		static std::shared_ptr<Image> CreateWithData(ePixel format, size_t width, size_t height, void const * data);
		static std::shared_ptr<Image> Create(ePixel format, size_t width, size_t height, uint8_t fill = 0);

	public: // make
		Image() = default;

		void reset(ePixel format, size_t width, size_t height, uint8_t byte);

		void resetWithData(ePixel format, size_t width, size_t height, void const * data);

	public: // get
		uint8_t * data() { return m_buffer.data(); }
		uint8_t const * data() const { return m_buffer.data(); }

		size_t size() const { return m_buffer.size(); }
		ePixel format() const { return m_format; }
		size_t width() const { return m_width; }
		size_t height() const { return m_height; }

	public: // fill
		void fillByte(uint8_t byte);
		void fillAlpha(uint8_t byte);
		void fillGrey(uint8_t byte);
		void fillRGB(Zen::Color3b rgb);
		void fillRGBA(Zen::Color4b rgba);

		/**
		 @ src must has same stride & larger(>=) height.

		 copy color and alpha.
		 if any self pixel changed, return true.
		 */
		bool fill(ePixel src_bpp, void const * src);
		/**
		 copy alpha only.
		 if no alpha channel, return false.
		 */
		bool fillAlpha(ePixel src_bpp, void const * src);
		/**
		 copy rgb(or grey). only.
		 */
		bool fillColor(ePixel src_bpp, void const * src);

	protected:
		Image(Image&) = default;

		std::vector<uint8_t> m_buffer;
		size_t m_width = 0;
		size_t m_height = 0;
		ePixel m_format = ePixel::None;
	};

	/**
	 use effect function or std::shared_ptr<ImageEffect>
	 */
	typedef std::function<std::shared_ptr<Image> (std::shared_ptr<Image>)> ImageEffectFunction;

	class ImageEffect {
	public:
		virtual ~ImageEffect() = default;

		virtual std::shared_ptr<Image> operator()(std::shared_ptr<Image> image) = 0;
	};

	typedef std::shared_ptr<ImageEffect> SharedImageEffect;

	class ImageEffectRainbow : public ImageEffect {
	public:
		/// move [0, 1
		ImageEffectRainbow(float angle, float move = 0);
		void setAngle(float angel);

		virtual std::shared_ptr<Image> operator()(std::shared_ptr<Image> image) override;

		static Color4f GetRainbowColor(float pos); // pos = 0..1

	protected:
		float m_x = 1, m_y = 0;
		float m_move = 0;
	};
}
